home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-04-28 | 25.0 KB | 842 lines | [TEXT/CWIE] |
- /*
- File: DriverGestaltExplorer.c
-
- Contains: A sample and tool for exploring Driver Gestalt.
-
- Written by: Quinn "The Eskimo!"
-
- Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- /////////////////////////////////////////////////////////////////
- // Standard Mac OS Interfaces
-
- #import <DriverGestalt.h>
-
- /////////////////////////////////////////////////////////////////
- // Standard C Libraries
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /////////////////////////////////////////////////////////////////
- // We use some of the utility routines from TradDriverLoaderLib,
- // which prevents us having to reinvent the wheel.
-
- #include "TradDriverLoaderLib.h"
-
- /////////////////////////////////////////////////////////////////
- #pragma mark ----- Utility Routines -----
-
- static void QAssert(Boolean mustBeTrue)
- // Stardard Assert functionality. How many times have
- // I written this? How much time would I save if it was
- // built into the OS?
- {
- if ( ! mustBeTrue ) {
- DebugStr("\pQAssert: Assertion failure");
- }
- }
-
- static DriverRefNum MapDriveToRefNum(SInt16 drive)
- // Walks the drive queue looking for the given drive
- // and returns the driver reference number of the driver
- // controlling the drive.
- //
- // I would have used UTFindDrive for this, but calling
- // it from PowerPC is tricky.
- {
- DrvQElPtr thisDrv;
-
- thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead;
- while (thisDrv != nil) {
- if (thisDrv->dQDrive == drive) {
- return thisDrv->dQRefNum;
- }
- thisDrv = (DrvQElPtr) thisDrv->qLink;
- }
- return 0;
- }
-
- static Boolean DriveSupportsDriverGestalt(SInt16 drive)
- // Returns true if the driver controlling the
- // supplied drive supports Driver Gestalt.
- {
- OSErr junk;
- DriverRefNum refNum;
- DriverFlags driverFlags;
-
- refNum = MapDriveToRefNum(drive);
-
- junk = TradGetDriverInformation(refNum, nil, &driverFlags, nil, nil);
- QAssert(junk == noErr);
- return TradDriverGestaltIsOn(driverFlags);
- }
-
- static StringPtr RefNumToName(DriverRefNum refNum)
- // Returns the (Pascal string) name of the driver with the supplied
- // refNum. Basically a wrapper around TradDriverLoaderLib.
- //
- // Note that the routine returns the address of a static
- // buffer, so you don't have to dispose it but you must
- // be careful not to call the routine again until you're
- // done with the result.
- {
- static Str255 nonReentrantBuffer;
- OSErr junk;
-
- junk = TradGetDriverInformation(refNum, nil, nil, nonReentrantBuffer, nil);
- QAssert(junk == noErr);
- return nonReentrantBuffer;
- }
-
- static char *OSTypeToString(OSType selector)
- // Returns a C string for the supplied selector.
- //
- // Note that the routine returns the address of a static
- // buffer, so you don't have to dispose it but you must
- // be careful not to call the routine again until you're
- // done with the result.
- {
- static char nonReentrantBuffer[5];
-
- *((OSType*) nonReentrantBuffer) = selector;
- nonReentrantBuffer[4] = 0;
- return nonReentrantBuffer;
- }
-
- /////////////////////////////////////////////////////////////////
- #pragma mark ----- Data Table Types -----
-
- // An array of OSTypeElement's is passed as the argument
- // to OSTypeDisplay. The array is terminated by an element
- // whose name is nil. This array allows OSTypeDisplay to
- // map an OSType to its string description.
-
- struct OSTypeElement {
- OSType value;
- char* name;
- };
- typedef struct OSTypeElement OSTypeElement;
-
- // The address of a BooleanTable is passed as the argument
- // to BooleanDisplay. The table allows BooleanDisplay to
- // map a Boolean result to a string description.
-
- struct BooleanTable {
- char *trueString;
- char *falseString;
- };
- typedef struct BooleanTable BooleanTable;
-
- // An array of FlagElement's is passed as the argument
- // to Flags16Display and Flags32Display, and hence on
- // to PrintFlags. The array is terminated by an element
- // whose mask is 0. This array allows PrintFlags to
- // test for the known flags in a flags UInt32 and print
- // out the corresponding textual descriptions.
-
- struct FlagElement {
- UInt32 mask;
- char *trueString;
- char *falseString;
- };
- typedef struct FlagElement FlagElement;
-
- // A GestaltElement holds information about a single
- // DriverGestalt selector, including the selector itself,
- // a textual description of the selector (name), the address
- // of a routine that can print the response, and the argument
- // for that routine.
- //
- // The primary use of this type is in gGestaltList,
- // an array of these elements (terminated by an entry with
- // a selector of 0) which describes all the Driver Gestalt
- // selectors documented at the time this sample was last updated.
-
- typedef void (*ResponseDisplayProc)(DriverGestaltParam *pb, void *arg);
-
- struct GestaltElement {
- OSType selector;
- char* name;
- ResponseDisplayProc responseDisplayRoutine;
- void* responseDisplayArg;
- };
- typedef struct GestaltElement GestaltElement;
-
- /////////////////////////////////////////////////////////////////
- #pragma mark ----- Response Printing -----
-
- // The routines in this section are responsible for taking a
- // Driver Gestalt response and printing it to stdout. They
- // all conform to the ResponseDisplayProc type and are referenced
- // by gGestaltList table.
- //
- // The routines are given in the order of most generic to most
- // specific.
-
- static void DefaultDisplay(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response for a selector we
- // don't know about. All we can do is print the four
- // standard response fields as hex.
- {
- #pragma unused(arg)
- printf(" driverGestaltResponse = %08lx\n", pb->driverGestaltResponse);
- printf(" driverGestaltResponse1 = %08lx\n", pb->driverGestaltResponse1);
- printf(" driverGestaltResponse2 = %08lx\n", pb->driverGestaltResponse2);
- printf(" driverGestaltResponse3 = %08lx\n", pb->driverGestaltResponse3);
- }
-
- static void OSTypeDisplay(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response in driverGestaltResponse
- // whose value is an OSType. arg is a pointer to an array
- // of OSTypeElements that describes the expected values
- // and their textual descriptions.
- {
- OSType response;
- OSTypeElement *responseList;
- Boolean found;
- ItemCount thisIndex;
-
- response = (OSType) pb->driverGestaltResponse;
- responseList = (OSTypeElement *) arg;
-
- // Search for response in the responseList.
-
- found = false;
- thisIndex = 0;
- while ( ! found && responseList[thisIndex].name != nil ) {
- found = (responseList[thisIndex].value == response);
- if ( ! found ) {
- thisIndex += 1;
- }
- }
-
- // If we found it, print the response with its textual description,
- // otherwise just print the response.
-
- if (found) {
- printf(" Response = '%s' “%s”\n", OSTypeToString(response), responseList[thisIndex].name);
- } else {
- printf(" Response = '%s'\n", OSTypeToString(response));
- }
- }
-
- static void BooleanDisplay(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response which is a Boolean in the
- // first byte of driverGestaltResponse. arg is a pointer to
- // an array of BooleanElements that gives the textual descriptions
- // for true and false.
- {
- BooleanTable *booleanTable;
- Boolean value;
-
- booleanTable = (BooleanTable *) arg;
- value = *GetDriverGestaltBooleanResponse(pb);
- switch (value) {
- case true:
- printf(" Response = %d “%s”\n", value, booleanTable->trueString);
- break;
- case false:
- printf(" Response = %d “%s”\n", value, booleanTable->falseString);
- break;
- default:
- printf(" Response = %d (Weird)\n", value);
- break;
- }
- }
-
- static void PrintFlags(UInt32 flags, FlagElement flagList[])
- // A utility routine called by Flags16Display and Flags32Display.
- // flags is the response flags to be printed. The routine
- // prints both the value of flags and a textual description
- // of the flags based on flagList, an array of FlagElements
- // which describes the known flag masks and the textual
- // descriptions for those masks.
- {
- ItemCount thisIndex;
-
- printf(" Response = %08lx\n", flags);
- thisIndex = 0;
- while ( flagList[thisIndex].mask != 0 ) {
- if ( (flags & flagList[thisIndex].mask) != 0 ) {
- printf(" %s\n", flagList[thisIndex].trueString);
- } else {
- printf(" %s\n", flagList[thisIndex].falseString);
- }
- thisIndex += 1;
- }
- }
-
- static void Flags16Display(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response which is a UInt32 in the
- // first two bytes of driverGestaltResponse. arg is a pointer to
- // an array of FlagElements which describes the known flag masks and
- // the textual descriptions for those masks.
- {
- UInt32 flags;
-
- flags = *((UInt16 *) &pb->driverGestaltResponse);
- PrintFlags(flags, arg);
- }
-
- static void Flags32Display(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response which is a UInt32 in the
- // driverGestaltResponse. arg is a pointer to an array of
- // FlagElements which describes the known flag masks and
- // the textual descriptions for those masks.
- {
- UInt32 flags;
-
- flags = *((UInt32 *) &pb->driverGestaltResponse);
- PrintFlags(flags, arg);
- }
-
- static void PowerDisplay(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt power response, used by the
- // various power rating selectors to return the
- // power in microWatts. arg is unused.
- {
- #pragma unused(arg)
- DriverGestaltPowerResponse* response;
-
- response = GetDriverGestaltPowerResponse(pb);
- printf(" Response = %ld microWatts\n", response->powerValue);
- }
-
- static void VersionDisplay(DriverGestaltParam *pb, void *arg)
- // Prints a Driver Gestalt response which is a NumVersion in
- // driverGestaltResponse. arg is unused.
- {
- #pragma unused(arg)
- NumVersion version;
- char versionString[256];
- char tmpString[256];
- char stageChar;
-
- version = *((NumVersion *) &pb->driverGestaltResponse);
-
- sprintf(versionString, "%d.%d", version.majorRev, (version.minorAndBugRev >> 4) & 0x0f);
- if ( (version.minorAndBugRev & 0x0f) != 0 ) {
- sprintf(tmpString, ".%d", version.minorAndBugRev & 0x0f);
- strcat(versionString, tmpString);
- }
- if ( version.stage != finalStage || version.nonRelRev != 0 ) {
- switch (version.stage) {
- case finalStage:
- stageChar = 'f';
- break;
- case betaStage:
- stageChar = 'b';
- break;
- case alphaStage:
- stageChar = 'a';
- break;
- case developStage:
- stageChar = 'd';
- break;
- default:
- stageChar = '?';
- break;
- }
- sprintf(tmpString, "%c%d", stageChar, version.nonRelRev);
- strcat(versionString, tmpString);
- }
-
- printf(" Response = %s (%08lx)\n", versionString, pb->driverGestaltResponse);
- }
-
- static void BootDisplay(DriverGestaltParam *pb, void *arg)
- // Prints the response to the Driver Gestalt kdgBoot selector,
- // which is a DriverGestaltBootResponse. arg is unused.
- {
- #pragma unused(arg)
- DriverGestaltBootResponse* response;
-
- response = GetDriverGestaltBootResponse(pb);
- printf(" extDev = %d\n", response->extDev);
- printf(" partition = %d\n", response->partition);
- printf(" SIMSlot = %d\n", response->SIMSlot);
- printf(" SIMsRSRC = %d\n", response->SIMsRSRC);
- }
-
- static void PurgeDisplay(DriverGestaltParam *pb, void *arg)
- // Prints the response to the Driver Gestalt kdgPurge selector,
- // which is a DriverGestaltBootResponse. arg is unused.
- {
- #pragma unused(arg)
- DriverGestaltPurgeResponse *response;
-
- response = GetDriverGestaltPurgeResponse(pb);
-
- PrintFlags(response->purgePermission, arg);
- printf(" purgeDriverPointer = %08lx\n", response->purgeDriverPointer);
- }
-
- static void FlushDisplay(DriverGestaltParam *pb, void *arg)
- // Prints the response to the Driver Gestalt kdgFlush selector,
- // which is a GetDriverGestaltFlushResponse. arg is unused.
- {
- #pragma unused(arg)
- DriverGestaltFlushResponse* response;
- char *tmpStr;
-
- response = GetDriverGestaltFlushResponse(pb);
- if (response->canFlush) {
- tmpStr = "Driver supports kdcFlush Driver Configure call";
- } else {
- tmpStr = "Driver does not support kdcFlush Driver Configure call";
- }
- printf(" canFlush = %d “%s”\n", response->canFlush, tmpStr);
- if (response->needsFlush) {
- tmpStr = "Driver needs flush when volume flushed";
- } else {
- tmpStr = "Driver does not need flush when volume flushed";
- }
- printf(" needsFlush = %d “%s”\n", response->needsFlush, tmpStr);
- }
-
- static void MediaInfoDisplay(DriverGestaltParam *pb, void *arg)
- // Prints the response to the Driver Gestalt kdgMediaInfo selector,
- // which is a DriverGestaltMediaInfoResponse. arg is unused.
- {
- #pragma unused(arg)
- DriverGestaltMediaInfoResponse* response;
-
- response = GetDriverGestaltMediaInfoResponse(pb);
- printf(" numberBlocks = %ld\n", response->numberBlocks);
- printf(" blockSize = %ld\n", response->blockSize);
- switch (response->mediaType) {
- case kMediaTypeUnknown:
- printf(" mediaType = “unknown”\n");
- break;
- case kMediaTypeCDROM:
- printf(" mediaType = “CD-ROM”\n");
- break;
- case kMediaTypeDVDROM:
- printf(" mediaType = “DVD-ROM”\n");
- break;
- case kMediaTypeNoMedia:
- printf(" mediaType = “no media”\n");
- break;
- }
- }
-
- /////////////////////////////////////////////////////////////////
- #pragma mark ----- Data Tables -----
-
- #pragma mark OSType Tables
-
- // gInterfaceTypeList describes the expected results
- // from the kdgInterface selector.
-
- static OSTypeElement gInterfaceTypeList[] = {
- {kdgScsiIntf, "SCSI"},
- {kdgPcmciaIntf, "PC Card"},
- {kdgATAIntf, "ATA"},
- {kdgFireWireIntf, "Firewire"},
- {kdgExtBus, "External Bus"},
- {0, nil}
- };
-
- // gDeviceTypeList describes the expected results
- // from the kdgDeviceType selector.
-
- static OSTypeElement gDeviceTypeList[] = {
- {kdgDiskType, "Disk"},
- {kdgTapeType, "Tape"},
- {kdgPrinterType, "Printer"},
- {kdgProcessorType, "Processor"},
- {kdgWormType, "Write-Once, Read Many"},
- {kdgCDType, "CD-ROM"},
- {kdgFloppyType, "Floppy"},
- {kdgScannerType, "Scanner"},
- {kdgFileType, "File (ie disk image)"},
- {kdgRemovableType, "Removable Disk"},
- {0, nil}
- };
-
- #pragma mark Boolean Tables
-
- // Boolean results from various selectors.
-
- static BooleanTable gSyncBooleanTable = { "Synchronous", "Asynchronous" };
- static BooleanTable gWideBooleanTable = { "Supports wide ioPosMode", "No support for wide ioPosMode" };
- static BooleanTable gPowerSwitchBooleanTable = { "Supports power switching", "No support for power switching" };
- static BooleanTable gHighPowerBooleanTable = { "In high power mode", "In low power mode" };
- static BooleanTable gSupportsPowerControlBooleanTable = { "Supports power control", "No support for power control" };
-
- #pragma mark Flag Tables
-
- // Flag results from various selectors.
-
- static FlagElement gPCXFlags[] = {
- { 0x01, "Supports PC Exchange calls", "No support for PC Exchange" },
- { 0, nil, nil}
- };
-
- static FlagElement gEjectFlags[] = {
- { kRestartDontEject_Mask, "Don't want eject at Restart", "Wants eject at Restart" },
- { kShutDownDontEject_Mask, "Don't want eject at Shutdown", "Wants eject at Shutdown" },
- { 0, nil, nil}
- };
-
- static FlagElement gVMOptionsFlags[] = {
- { kAllowVMNoneMask, "VM should never use this drive", "VM may use this drive" },
- { kAllowVMReadOnlyMask, "VM may use this drive read-only", "VM may not use this drive for read-only" },
- { kAllowVMReadWriteMask, "VM may use this drive read/write", "VM may not use this drive for read/write" },
- { 0, nil, nil}
- };
-
- static FlagElement gPurgeFlags[] = {
- { 1 << kbCloseOk, "Close OK", "Close not allowed" },
- { 1 << kbRemoveOk, "RemoveDriver OK", "RemoveDriver not allowed" },
- { 1 << kbPurgeOk, "DisposePtr OK", "DisposePtr not allowed" },
- { 0, nil, nil}
- };
-
- #pragma mark gGestaltList
-
- // The primary list of Driver Gestalt selectors that we understand.
- // This table allows us to map selectors to their textual descriptions,
- // and allows us to print a Driver Gestalt response by dispatching
- // to the appropriate display routines.
-
- static GestaltElement gGestaltList[] = {
- {kdgVersion, "Version", VersionDisplay, nil },
- {kdgDeviceType, "Device Type", OSTypeDisplay, gDeviceTypeList },
- {kdgInterface, "Interface Type", OSTypeDisplay, gInterfaceTypeList },
- {kdgSync, "Synchronous", BooleanDisplay, &gSyncBooleanTable },
- {kdgBoot, "Boot", BootDisplay, nil },
- {kdgWide, "Wide", BooleanDisplay, &gWideBooleanTable },
- {kdgPurge, "Purge Permission", PurgeDisplay, gPurgeFlags },
- {kdgSupportsSwitching, "Power Management", BooleanDisplay, &gPowerSwitchBooleanTable },
- {kdgMin3VPower, "Min 3.3 V Power", PowerDisplay, nil },
- {kdgMin5VPower, "Min 5 V Power", PowerDisplay, nil },
- {kdgMax3VPower, "Max 3.3 V Power", PowerDisplay, nil },
- {kdgMax5VPower, "Max 5 V Power", PowerDisplay, nil },
- {kdgInHighPower, "High Power Mode", BooleanDisplay, &gHighPowerBooleanTable },
- {kdgSupportsPowerCtl, "Power API Support", BooleanDisplay, &gSupportsPowerControlBooleanTable },
- {kdgAPI, "PC Exchange API Support", Flags16Display, gPCXFlags },
- {kdgEject, "Shutdown Eject Options", Flags32Display, gEjectFlags },
- {kdgFlush, "Flush Options", FlushDisplay, nil },
- {kdgVMOptions, "VM Options", Flags32Display, gVMOptionsFlags },
- {kdgMediaInfo, "Media Information", MediaInfoDisplay, nil},
- {0, nil, nil, nil }
- };
-
- /////////////////////////////////////////////////////////////////
- #pragma mark ----- User Interface Code -----
-
- static void PrintListOfDrives(void)
- // Prints a nicely formatted list of the drives
- // available on this machine by walking the drive
- // queue.
- {
- DrvQElPtr thisDrv;
-
- printf("Drive List\n");
- printf(" 0) <<<all drives>>>\n");
-
- thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead;
- while (thisDrv != nil) {
- printf(" %d) with driver %d “%#s”\n", thisDrv->dQDrive, thisDrv->dQRefNum, RefNumToName(thisDrv->dQRefNum));
- thisDrv = (DrvQElPtr) thisDrv->qLink;
- }
- }
-
- static void PrintListOfSelectors(void)
- // Prints a nicely formatted list of Driver Gestalt
- // selectors that we know about by walking our
- // gGestaltList table.
- {
- ItemCount thisElement;
-
- printf("Selector List\n");
- thisElement = 0;
- while ( gGestaltList[thisElement].selector != 0 ) {
- printf(" '%s' “%s”\n",
- OSTypeToString(gGestaltList[thisElement].selector),
- gGestaltList[thisElement].name
- );
- thisElement += 1;
- }
- }
-
- static SInt16 GetDriveNumber(void)
- // Asks the user to enter a drive number, returning
- // a negative value on error, a positive value for a specific
- // drive number, and 0 if the user wants to query all drives.
- {
- SInt16 result;
- char driveStr[256];
-
- PrintListOfDrives();
-
- printf("Enter a drive number:\n");
- gets(driveStr);
- if (driveStr[0] == 0) {
- result = -1;
- } else {
- result = atoi(driveStr);
- }
- return result;
- }
-
- typedef void (*ForEachDriveProc)(UInt32 refcon, SInt16 drive);
-
- static void ForEachDriveDo(SInt16 drive, ForEachDriveProc proc, UInt32 refcon)
- // This routine provides support for the users
- // desire to issue a Driver Gestalt query on all drives,
- // as specified by typing "0" in response to GetDriveNumber.
- // That drive number is passed in as the drive parameter
- // to this routine. If it's non-zero, this routine calls
- // the supplied proc with that drive as a parameter. If drive
- // is 0, this routine walks the drive queue, repeatedly calling
- // proc, once for each drive.
- {
- DrvQElPtr thisDrv;
-
- if (drive != 0) {
- proc(refcon, drive);
- } else {
- thisDrv = (DrvQElPtr) GetDrvQHdr()->qHead;
- while (thisDrv != nil) {
- proc(refcon, thisDrv->dQDrive);
- printf("\n");
- thisDrv = (DrvQElPtr) thisDrv->qLink;
- }
- }
- }
-
- static void SingleQuery(SInt16 drive, GestaltElement *element)
- // Perform a single Driver Gestalt query on a single
- // drive. element is typically an entry from gGestaltList,
- // which specifies which selector to query and how to print
- // the result.
- {
- OSErr err;
- DriverGestaltParam pb;
-
- // Set up the parameter block.
-
- pb.ioVRefNum = drive;
- pb.ioCRefNum = MapDriveToRefNum(drive);
- pb.csCode = kDriverGestaltCode;
- pb.driverGestaltSelector = element->selector;
-
- // Print out the query we're about to do.
-
- printf("'%s' (%s) on drive %d with driver %d “%#s”\n",
- OSTypeToString(element->selector),
- element->name,
- drive,
- pb.ioCRefNum,
- RefNumToName(pb.ioCRefNum)
- );
-
- // Check that the driver support Driver Gestalt. If it doesn't,
- // don't send the driver the query otherwise we might accidentally
- // trigger some action we didn't expect.
-
- if ( DriveSupportsDriverGestalt(drive) ) {
-
- // The drive support Driver Gestalt. Let's do the query
- // and print out the result.
-
- err = PBStatusSync((ParmBlkPtr) &pb);
- if (err == noErr) {
- QAssert(element->responseDisplayRoutine != nil);
- element->responseDisplayRoutine(&pb, element->responseDisplayArg);
- } else {
- printf(" Failed with error %d.\n", err);
- }
- } else {
- printf(" Driver %d does not support Driver Gestalt.\n", pb.ioCRefNum);
- }
-
- }
-
- static void OneQueryOnOneDrive(OSType selector, SInt16 drive)
- // This routine issues one specific Drive Gestalt query,
- // specified by selector, on one specific drive. The basic
- // operation is to search the gGestaltList array for the
- // selector. If we find it, we can pass the GestaltElement
- // to SingleQuery, which uses it to format the response.
- // If we can't find the query, we cook up our own local
- // GestaltElement (which indicates that the response should
- // be displayed by the DefaultDisplay routine) and use
- // that instead.
- {
- ItemCount thisElement;
- Boolean found;
- GestaltElement localElement;
-
- // Search gGestaltList for selector.
-
- thisElement = 0;
- found = false;
- while ( gGestaltList[thisElement].selector != 0 && ! found ) {
- found = (gGestaltList[thisElement].selector == selector);
- if ( ! found ) {
- thisElement += 1;
- }
- }
-
- // If we found it, use it to issue the query, otherwise
- // build our own local GestaltElement and issue the query
- // with that.
-
- if (found) {
- SingleQuery(drive, &gGestaltList[thisElement]);
- } else {
- localElement.selector = selector;
- localElement.name = "Unknown";
- localElement.responseDisplayRoutine = DefaultDisplay;
- localElement.responseDisplayArg = nil;
-
- SingleQuery(drive, &localElement);
- }
- }
-
- static void AllQueriesOnOneDrive(UInt32 refcon, SInt16 drive)
- // This routine queries all known Driver Gestalt selectors
- // on a specific drive. The refcon parameter is unused
- // but it's required because this routine is a callback
- // ForEachDriveDo.
- {
- #pragma unused(refcon)
- UInt32 thisElement;
- DriverRefNum refNum;
-
- if ( DriveSupportsDriverGestalt(drive) ) {
-
- // Walk our global list of known Driver Gestalt selectors
- // (gGestaltList) and call SingleQuery on each one.
-
- thisElement = 0;
- while ( gGestaltList[thisElement].selector != 0 ) {
- SingleQuery(drive, &gGestaltList[thisElement]);
- thisElement += 1;
- }
- } else {
-
- // The driver does not support Driver Gestalt. Stop now before
- // generating a huge cascade of "Driver does not support Driver Gestalt"
- // messages.
-
- refNum = MapDriveToRefNum(drive);
- printf("Drive %d with driver %d “%#s” does not support Driver Gestalt.\n",
- drive,
- refNum,
- RefNumToName(refNum)
- );
- }
- }
-
- static void DoOneQuery(void)
- // This is a primary user interface entry point. Ask
- // the user for a drive and selector and then issue
- // the query.
- {
- SInt16 drive;
- char selectorStr[256];
- OSType selector;
-
- drive = GetDriveNumber();
- if (drive >= 0) {
- do {
- printf("Enter a selector (“?” for a list):\n");
- gets(selectorStr);
- if ( strcmp(selectorStr, "?") == 0 ) {
- PrintListOfSelectors();
- }
- } while ( strcmp(selectorStr, "?") == 0 );
- if (selectorStr[0] != 0) {
- selector = *((OSType *) &selectorStr[0]);
- ForEachDriveDo(drive, OneQueryOnOneDrive, selector);
- }
- }
- }
-
- static void DoAllQueries(void)
- // This is a primary user interface entry point.
- // Ask the user for a drive and then query all
- // known Driver Gestalt selectors on that drive.
- {
- SInt16 drive;
- char selectorStr[256];
- OSType selector;
-
- drive = GetDriveNumber();
- if (drive >= 0) {
- selector = *((OSType *) &selectorStr[0]);
- ForEachDriveDo(drive, AllQueriesOnOneDrive, 0);
- }
- }
-
- static void PrintHelp(void)
- // This is a primary user interface entry point.
- // Print the list of supported commands.
- {
- printf("g) Issue a Driver Gestalt query\n");
- printf("G) Query all known Driver Gestalt selectors\n");
- printf("?) Help\n");
- printf("q) Quit\n");
- }
-
- void main(void)
- // The main entry point. A trivial console application
- // that waits for a command to be typed and then performs
- // the command.
- {
- Boolean quitNow;
- char command[256];
-
- printf("Hello Cruel World!\n");
- printf("\n");
- printf("Driver Gestalt Explorer\n");
- printf("-- A simple command line program for exploring\n");
- printf("-- the Drive Gestalt values returned by block\n");
- printf("-- device drivers\n");
- printf("\n");
-
- PrintHelp();
- quitNow = false;
- do {
- printf("\n");
- printf("Enter a command:\n");
- gets(command);
- switch (command[0]) {
- case 'g':
- DoOneQuery();
- break;
- case 'G':
- DoAllQueries();
- break;
- case '?':
- PrintHelp();
- break;
- case 'q':
- quitNow = true;
- break;
- default:
- printf("Huh?\n");
- break;
- }
- } while ( ! quitNow );
-
- printf("Done. Press command-Q to Quit.\n");
- }
-